/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../macro/head.h"
#include "objs.h"
#include "hook.h"
#include "mgr.h"

namespace xos_http_protocol
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    struct cmp_char
    {
        bool operator()( char const * a, char const * b ) const
        {
            return mgr::container()->crt()->strcmp( a, b ) < 0;
        }
    };

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    typedef std::map< const char *, const char *, cmp_char > HTTP_TYPE_MAP;
    typedef HTTP_TYPE_MAP::iterator HTTP_TYPE_ITER;

    static HTTP_TYPE_MAP * http_compress_type_map_ptr = 0;
    static HTTP_TYPE_MAP * http_content_type_map_ptr = 0;

    static xos_container::i_container * container_ptr = 0;
    static mgr * mgr_ptr = 0;

    static f_session session_fun_ptr = 0;
    static f_cookie cookie_fun_ptr = 0;

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    mgr::mgr()
    {
    }

    mgr::~mgr()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::static_init( xos_container::i_container * pContainer, i_http_mgr ** ppv )
    {
        return xos_stl::static_init_module( pContainer, ppv, container_ptr, mgr_ptr );
    }

    xos_container::i_container * mgr::container()
    {
        return container_ptr;
    }

    mgr * mgr::get()
    {
        return mgr_ptr;
    }

    int mgr::valid_value( const char * lpszKey, const char * lpszStr )
    {
        xos::i_crt * pCrt = mgr::container()->crt();
        int nLen = MAX_VALUE_LENGTH;
        if( 0 == pCrt->strcmp( HTTP_COOKIE, lpszKey ) )
        {
            nLen = MAX_HTTP_REQUEST_HEAD_COOKIE_VALUE_LENGTH;
        }
        int ret = container()->common()->misc()->valid( lpszStr, nLen );
        ret = ( 0 == ret ) ? 0 : -1;
        return ret;
    }

    int mgr::valid_key( const char * lpszStr )
    {
        int ret = container()->common()->misc()->valid( lpszStr, MAX_KEY_LENGTH );
        ret = ( 0 == ret ) ? 0 : -1;
        return ret;
    }

    int mgr::valid_uri( const char * lpszStr )
    {
        int ret = container()->common()->misc()->valid( lpszStr, MAX_URI_LENGTH );
        ret = ( 0 == ret ) ? 0 : -1;
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // html & gz
    // 

    int mgr::fmt_simple_html( xos_box::i_string * pHtml, const char * lpszTitle, const char * lpszInfo )
    {
        int ret = 0;

        mgr::container()->crt()->sprintf( pHtml,
            "<!DOCTYPE html>\r\n\
<html>\r\n\
<head>\r\n\
<meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\">\r\n\
<title>%s</title>\r\n\
</head>\r\n\r\n\
<body>\r\n\
<p>%s</p>\r\n\
</body>\r\n\
</html>",
lpszTitle, lpszInfo );

        return ret;
    }

    bool mgr::if_need_compress_by_mime( const char * lpszMime, int nSize )
    {
        xos_box::i_str_property * pProp = (xos_box::i_str_property *)mgr::container()->config()->get( "xos_gzip_config" );
        if( !pProp )
        {
            return false;
        }
        bool bRet = false;
        int ret = 0;
        xos_box::i_list * pList = pProp->list( "compress_mime_type_list" );
        int nMinSize = pProp->i32( "compress_min_size" );
        xos::i_crt * pCrt = mgr::container()->crt();
        xos_box::i_list_iter * pListIter = 0;
        xos_box::i_variant * pV = 0;
        if( ( 0 == ret ) && ( ( nSize < nMinSize ) || !lpszMime ) )
        {
            ret = 1;
        }
        if( 0 == ret )
        {
            if( pList )
            {
                pListIter = pList->begin();
                pListIter->reset();
            }
            else
            {
                ret = 2;
            }
        }
        while( ( 0 == ret ) && !bRet && ( ( pV = (xos_box::i_variant *)pListIter->next() ) ) )
        {
            const char * lpszStr = pV->str();
            int nRet = pCrt->strcmp( lpszStr, lpszMime );
            if( 0 == nRet )
            {
                bRet = true;
            }
        }
        xos_stl::release_interface( pListIter );
        return bRet;
    }

    bool mgr::if_need_compress_by_ext( const char * lpszExt, int nSize )
    {
        const char * pMime = get_mime_by_ext( lpszExt );
        bool bRet = false;
        if( pMime )
        {
            bRet = if_need_compress_by_mime( pMime, nSize );
        }
        return bRet;
    }

    const char * mgr::get_mime_by_ext( const char * lpszExt )
    {
        xos_box::i_str_property * pProp = (xos_box::i_str_property *)mgr::container()->config()->get( "xos_http_config" );
        if( !pProp )
        {
            return 0;
        }
        xos_box::i_str_property * pMime = 0;
        const char * pRet = 0;
        if( pProp )
        {
            pMime = pProp->str_prop( "mime", 0 );
        }
        if( pMime )
        {
            pRet = pMime->str( lpszExt );
        }
        return pRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // compress
    // 

    int mgr::init_compress_type( xos_box::i_list * pTypeList )
    {
        int ret = 0;

        HTTP_TYPE_MAP & mp = *http_compress_type_map_ptr;
        xos_box::i_variant * pVT = 0;
        pTypeList->reset();

        while( ( pVT = (xos_box::i_variant *)pTypeList->next() ) )
        {
            xos_box::i_str_property * pProp = pVT->str_prop( 0 );
            const char * lpszType = pProp->str( "type" );
            mp[lpszType] = lpszType;
        }

        return ret;
    }

    const char * mgr::compress_type( const char * lpszType )
    {
        int ret = 0;

        HTTP_TYPE_MAP & mp = *http_compress_type_map_ptr;
        const char * pRet = 0;

        if( 0 == ret )
        {
            HTTP_TYPE_ITER iter = mp.find( lpszType );
            if( iter != mp.end() )
            {
                pRet = iter->second;
            }
        }

        return pRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // content type
    // 

    int mgr::init_content_type( xos_box::i_list * pTypeList )
    {
        int ret = 0;

        HTTP_TYPE_MAP & mp = *http_content_type_map_ptr;
        xos_box::i_variant * pVT = 0;
        pTypeList->reset();

        while( ( pVT = (xos_box::i_variant *)pTypeList->next() ) )
        {
            xos_box::i_str_property * pProp = pVT->str_prop( 0 );
            const char * lpszName = pProp->str( "extension" );
            const char * lpszType = pProp->str( "type" );
            mp[lpszName] = lpszType;
        }

        return ret;
    }

    const char * mgr::content_type( const char * lpszFile )
    {
        int ret = 0;

        HTTP_TYPE_MAP & mp = *http_content_type_map_ptr;
        const char * lpszExt = 0;
        const char * pRet = 0;

        if( 0 == ret )
        {
            lpszExt = mgr::container()->common()->misc()->ext( lpszFile, 0 );
            if( !lpszExt )
            {
                ret = 1;
            }
        }

        if( 0 == ret )
        {
            HTTP_TYPE_ITER iter = mp.find( lpszExt );
            if( iter != mp.end() )
            {
                pRet = iter->second;
            }
        }

        return pRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // session_impl & cookie_impl callback
    // 

    f_session mgr::session_callback( f_session * ppFun )
    {
        f_session pRet = session_fun_ptr;
        if( ppFun )
        {
            session_fun_ptr = *ppFun;
            pRet = *ppFun;
        }
        return pRet;
    }

    f_cookie mgr::cookie_callback( f_cookie * ppFun )
    {
        f_cookie pRet = cookie_fun_ptr;
        if( ppFun )
        {
            cookie_fun_ptr = *ppFun;
            pRet = *ppFun;
        }
        return pRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 
    // 创建package功能接口
    // 

    i_compose_request * mgr::compose_request()
    {
        compose_request_impl::T * pRet = 0;
        xos_stl::init_pool_item( pRet );
        return pRet;
    }

    i_parse_request * mgr::parse_request()
    {
        parse_request_impl::T * pRet = 0;
        xos_stl::init_pool_item( pRet );
        return pRet;
    }

    i_compose_return * mgr::compose_return()
    {
        compose_return_impl::T * pRet = 0;
        xos_stl::init_pool_item( pRet );
        return pRet;
    }

    i_parse_return * mgr::parse_return()
    {
        parse_return_impl::T * pRet = 0;
        xos_stl::init_pool_item( pRet );
        return pRet;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // 简便创建对象方法
    // 

    http::i_session * mgr::session( const char * lpszSessionId )
    {
        session_impl * pRet = session_impl::get( lpszSessionId );
        return pRet;
    }

    http::i_cookie * mgr::cookie()
    {
        cookie_impl::T * pT = 0;
        xos_stl::init_pool_item( pT );
        return pT;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // heart
    //
    int mgr::heart( int interval_ms )
    {
        int ret = 0;
        session_impl::heart( interval_ms );
        return ret;
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::put_back_to_pool()
    {
        int ret = 0;
        delete this;
        return ret;
    }

    int mgr::init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            xos_stl::init_obj( http_compress_type_map_ptr );
        }

        if( 0 == ret )
        {
            xos_stl::init_obj( http_content_type_map_ptr );
        }

        if( 0 == ret )
        {
            ret = hook::init();
        }

        return ret;
    }

    int mgr::term()
    {
        int ret = 0;

        hook::term();

        xos_stl::term_obj( http_compress_type_map_ptr );
        xos_stl::term_obj( http_content_type_map_ptr );

        mgr_ptr = 0;
        container_ptr = 0;

        return ret;
    }

} // xos_http_protocol
